package fr.upmc.i3s.upmcontact.views.fragments;

import java.util.LinkedList;
import java.util.List;

import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TextView;
import fr.upmc.i3s.upmcontact.Constants;
import fr.upmc.i3s.upmcontact.R;
import fr.upmc.i3s.upmcontact.backend.BackEndBridgeImpl;
import fr.upmc.i3s.upmcontact.callbacks.IGetDataCallback;
import fr.upmc.i3s.upmcontact.callbacks.ISwipeCallback;
import fr.upmc.i3s.upmcontact.callbacks.IUpdateDataCallback;
import fr.upmc.i3s.upmcontact.content.collectors.CollectorsController;
import fr.upmc.i3s.upmcontact.content.collectors.UpdateDatesManager;
import fr.upmc.i3s.upmcontact.content.containers.CollectedContentManager;
import fr.upmc.i3s.upmcontact.content.containers.IContainer;
import fr.upmc.i3s.upmcontact.contents.LostFoundObject;
import fr.upmc.i3s.upmcontact.librairies.pulltorefresh.PullToRefreshBase;
import fr.upmc.i3s.upmcontact.librairies.pulltorefresh.PullToRefreshScrollView;
import fr.upmc.i3s.upmcontact.librairies.pulltorefresh.PullToRefreshBase.OnRefreshListener;
import fr.upmc.i3s.upmcontact.listeners.OnObjectClickListener;
import fr.upmc.i3s.upmcontact.tools.BitmapFactoryAdapter;
import fr.upmc.i3s.upmcontact.tools.DateUtils;
import fr.upmc.i3s.upmcontact.tools.FileUtils;
import fr.upmc.i3s.upmcontact.tools.SwipeDetector;
import fr.upmc.i3s.upmcontact.tools.SwipeDetector.Action;
import fr.upmc.i3s.upmcontact.views.FragmentController;
import fr.upmc.i3s.upmcontact.views.dialogs.ObjectDetailsDialog;
import fr.upmc.i3s.upmcontact.views.fragments.models.IFragmentModel;
import fr.upmc.i3s.upmcontact.views.fragments.models.PageFragmentModel;

public class FeedFoundObjectsFragment extends PageFragmentModel implements IFragmentModel {
	
	private static final String TAG = "FeedFoundObjectsFragment";
	
	private static final int REQUEST_CHANGE_STATUS = 1994;
	
	private FragmentController fragmentController;
	private static volatile FeedFoundObjectsFragment INSTANCE;
	
	private PullToRefreshScrollView prsvContent;
	private TableLayout tlFeed;
	private TextView tvFeetLeft;
	private TextView tvFeetRight;
	private ImageView ivFeetRight;
	
	public static FeedFoundObjectsFragment getInstance() {
		if(INSTANCE == null) {
			FeedFoundObjectsFragment fragment = new FeedFoundObjectsFragment();
		    Bundle bundle = new Bundle(3);
		    bundle.putInt(EXTRA_LAYOUT_FRAGMENT, R.layout.fragment_feed);
		    bundle.putInt(EXTRA_HEAD_ICON, R.drawable.ic_menu_found_white);
		    bundle.putInt(EXTRA_HEAD_TEXT, R.string.title_fragment_found_object);
		    fragment.setArguments(bundle);
		    INSTANCE = fragment;
		}
	    return INSTANCE;
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return super.onCreateView(inflater, container, savedInstanceState);
	}
	
 	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.initFragmentViews();
		this.fragmentController = (FragmentController) getActivity();
		fetchViews();
		customizeViews();
		setListeners();
	}
 	
 	@Override
 	public void fetchViews() {
 		this.prsvContent = (PullToRefreshScrollView) this.getView().findViewById(R.id.pullToRefreshScrollview_content);
 		this.tlFeed = (TableLayout) this.getView().findViewById(R.id.tableLayout_feed);
 		this.tvFeetLeft = (TextView) this.getView().findViewById(R.id.textView_feet_text_left);
 		this.tvFeetRight = (TextView) this.getView().findViewById(R.id.textView_feet_text_right);
 		this.ivFeetRight = (ImageView) this.getView().findViewById(R.id.imageView_feet_arrow_right);
 	}
 	
 	@Override
 	public void customizeViews() {
 		this.fragmentController.getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
 		this.tvFeetLeft.setText(R.string.action_goto_lost);
 		this.tvFeetRight.setText("");
 		this.ivFeetRight.setImageBitmap(null);
 		// set last update date for pull to refresh :
 		updateDate();
 		// fill table row feed with lost objects :
 		fillFeed();
 	}
 	
	private void updateDate() {
 		this.prsvContent.getLoadingLayoutProxy().setLastUpdatedLabel(
 				fragmentController.getString(R.string.pull_to_refresh_last_update)+" "+
 				DateUtils.toDisplayDateTime(UpdateDatesManager.retrieveUpdateFoundObjectsDate(fragmentController)));
	}
 	
 	private void fillFeed() {
 		tlFeed.removeAllViews();
 		LayoutInflater inflater = (LayoutInflater) fragmentController.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 		for(LostFoundObject lfo : CollectedContentManager.getInstance(getActivity()).getFoundObjects()) {
 			Log.i(TAG, "LostFoundObject="+lfo);
 			tlFeed.addView(createRowForObject(inflater, lfo));
 			tlFeed.addView(createSeparator(inflater));
 		}
 	}
 	
 	@Override
 	public void setListeners() {
 		this.prsvContent.setOnRefreshListener(onContentRefreshListener);
 		this.tvFeetLeft.setOnClickListener(onFeetLeftClickListener);
 	}
 	
	@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {  
		if(requestCode == REQUEST_CHANGE_STATUS && resultCode == Activity.RESULT_OK) {
			if(data.getExtras() != null) {
				LostFoundObject lfo = (LostFoundObject) data.getExtras().get(ObjectDetailsDialog.PARAM_OBJECT);
				if(lfo != null) {
					int newStatus = data.getExtras().getInt(ObjectDetailsDialog.PARAM_NEW_STATUS, BackEndBridgeImpl.PARSE_OBJECT_STATUS_SIGNALED);
					BackEndBridgeImpl.getInstance(fragmentController).updateLostFoundObject(updateObjectCallback, lfo, newStatus);
				}
			}
		}
	}
 	
 	private View createRowForObject(LayoutInflater inflater, LostFoundObject lfo) {
 		View row = inflater.inflate(R.layout.layout_row_object, null);
 		// fetch views
 		ImageView ivIcon = (ImageView) row.findViewById(R.id.imageView_row_object);
 		TextView tvName = (TextView) row.findViewById(R.id.textView_row_object_name);
 		TextView tvPlace = (TextView) row.findViewById(R.id.textView_row_object_place);
 		TextView tvDesc = (TextView) row.findViewById(R.id.textView_row_object_description);
 		TextView tvUser = (TextView) row.findViewById(R.id.textView_row_object_signaled_by);
 		TextView tvDate = (TextView) row.findViewById(R.id.textView_row_object_signaled_at_date);
 		TextView tvHour = (TextView) row.findViewById(R.id.textView_row_object_signaled_at_hour);
 		// custom views
 		tvName.setText(lfo.getName());
 		tvPlace.setText(lfo.getPlace());
 		tvDesc.setText(lfo.getDescription());
 		tvUser.setText(lfo.getSignaledBy().getUsername());
 		tvDate.setText(DateUtils.toDisplayDate(lfo.getCreatedAt()));
 		tvHour.setText(DateUtils.toDisplayTime(lfo.getCreatedAt()));
 		if(lfo.getPhotoPath() != null) { 
 			Bitmap bm = BitmapFactoryAdapter.decodeFile(lfo.getPhotoPath(), 250);
 			ivIcon.setImageBitmap(bm);
 		}
 		row.setOnTouchListener(swipeDetector);
 		row.setOnClickListener(new OnObjectClickListener(this, lfo, REQUEST_CHANGE_STATUS));
 		// change IDs
 		int randId = (int) Math.round(Math.random()*1000);
 		row.setId(row.getId()+randId);
 		tvName.setId(tvName.getId()+randId);
 		tvPlace.setId(tvPlace.getId()+randId);
 		tvDesc.setId(tvDesc.getId()+randId);
 		tvUser.setId(tvUser.getId()+randId);
 		tvDate.setId(tvDate.getId()+randId);
 		tvHour.setId(tvHour.getId()+randId);
 		ivIcon.setId(ivIcon.getId()+randId);
 		return row;
 	}
 	
    private View createSeparator(LayoutInflater inflater) {
        View separator = inflater.inflate(R.layout.layout_separator, null);
        return separator;
    }

 	
	  ///////////////
	 // CALLBACKS //
	///////////////
	
	private ISwipeCallback swipeCallback = new ISwipeCallback() {
		@Override
		public void perfomedSwipe(View view, Action action) {
			switch(action) {
			case FROM_L_TO_R:
				view.setFocusable(false);
				view.setOnClickListener(null);
				view.setOnTouchListener(null);
				fragmentController.switchContent(
						FeedLostObjectsFragment.getInstance(),
						FragmentController.TRANSACTION_FROM_LEFT_TO_RIGHT);
				break;
			default:
				break;
			}
		}
	};
 	
	
	private IGetDataCallback getFoundObjectsCallback = new IGetDataCallback() {
		@Override
		public void getDataEndedOk(LinkedList<Object> list) {
			Log.i(TAG, "getFoundObjectsCallback.getDataEndedOk.list.size="+list.size());
			CollectedContentManager.getInstance(fragmentController).getFoundObjects().updateWith(list);
			UpdateDatesManager.storeFoundObjectsUpdateDate(getActivity());
			// sort by ascending date
			CollectedContentManager.getInstance(fragmentController).getFoundObjects().sortBy(IContainer.DESCENDING);
			// save content for offline access :
			CollectedContentManager.getInstance(fragmentController).getFoundObjects().saveState(fragmentController);
			// delete unused local files :
			List<String> exceptedFiles = CollectedContentManager.getInstance(fragmentController).getFoundObjects().getRequiredExternalFileList();
			FileUtils.rmAllFilesInDirectoryExcept(Constants.FOUND_EXTERNAL_FOLDER, exceptedFiles);
	 		// set last update date for pull to refresh :
	 		updateDate();
			// feel feed view :
			fillFeed();
			prsvContent.onRefreshComplete();
		}
		@Override
		public void getDataEndedNok() {
			Log.w(TAG, "getFoundObjectsCallback.getDataEndedNok");
			prsvContent.onRefreshComplete();
		}
	};
	
	
	private IUpdateDataCallback updateObjectCallback = new IUpdateDataCallback() {
		@Override
		public void updated(Object objectBeforeUpdate, boolean success) {
			Log.d(TAG, "updateObjectCallback.success="+success);
			if(success) {
				LostFoundObject lfo = (LostFoundObject) objectBeforeUpdate;
				CollectedContentManager.getInstance(fragmentController).getFoundObjects().removeById(lfo.getId());
				UpdateDatesManager.storeFoundObjectsUpdateDate(getActivity());
				// save content for offline access :
				CollectedContentManager.getInstance(fragmentController).getFoundObjects().saveState(fragmentController);
				// delete unused local files :
				List<String> exceptedFiles = CollectedContentManager.getInstance(fragmentController).getFoundObjects().getRequiredExternalFileList();
				FileUtils.rmAllFilesInDirectoryExcept(Constants.FOUND_EXTERNAL_FOLDER, exceptedFiles);
		 		// re-use dialog in backendbridge
				BackEndBridgeImpl.getInstance(fragmentController).setCancelForAWhile(false);
				// feel feed view :
				fillFeed();
			}
		}
	};
 	
	  ///////////////
	 // LISTENERS //
	///////////////
	
	private SwipeDetector swipeDetector = new SwipeDetector(swipeCallback);
	
	private OnRefreshListener<ScrollView> onContentRefreshListener = new OnRefreshListener<ScrollView>() {
		@Override
		public void onRefresh(PullToRefreshBase<ScrollView> refreshView) {
			Log.i(TAG, "onContentRefreshListener.onRefresh");
			CollectorsController.getInstance(fragmentController)
			.getFoundObjectsCollector()
			.collect(fragmentController, getFoundObjectsCallback, true, true);
		}
	};
	
 	private OnClickListener onFeetLeftClickListener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			fragmentController.switchContent(
					FeedLostObjectsFragment.getInstance(),
					FragmentController.TRANSACTION_FROM_LEFT_TO_RIGHT);
		}
	};
	
}
